using System;
using System.Collections.Generic;
using System.Text;

namespace SharpMUD.Framework.IO
{
    /// <summary>
    /// A custom implementation of System.Text.Encoding that properly encodes
    /// ASCII characters up to the '255' value.
    /// </summary>
    /// <remarks>
    /// The System.Text.ASCIIEncoding (also acquired using the "ASCII" property of 
    /// the static class System.Text.Encoding), only encodes values 0 through 127.
    /// Since ASCII values 0 through 255 completely correspond with Unicode, and
    /// the full range is needed for ASCII art, this implementation is required.
    /// </remarks>
    public class FullASCIIEncoding : System.Text.Encoding
    {
        private System.Text.Encoding _BackupEncoding;

        public FullASCIIEncoding()
        {
            _BackupEncoding = System.Text.Encoding.ASCII;
        }

        public override int GetByteCount(char[] chars, int index, int count)
        {
            return count;
        }

        public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
        {
            int currentCharIndex = 0;
            int currentByteIndex = 0;
            for (int x = 0; x < charCount; x++)
            {
                currentCharIndex = charIndex + x;
                currentByteIndex = byteIndex + x;
                bytes[currentByteIndex] = this.ConvertChar(chars[currentCharIndex]);
            }
            return charCount;
        }

        public override int GetCharCount(byte[] bytes, int index, int count)
        {
            return count;
        }

        public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
        {
            int currentCharIndex = 0;
            int currentByteIndex = 0;
            for (int x = 0; x < byteCount; x++)
            {
                currentCharIndex = charIndex + x;
                currentByteIndex = byteIndex + x;
                chars[currentCharIndex] = this.ConvertByte(bytes[currentByteIndex]);
            }
            return byteCount;
        }

        public override int GetMaxByteCount(int charCount)
        {
            return charCount;
        }

        public override int GetMaxCharCount(int byteCount)
        {
            return byteCount;
        }

        private char ConvertByte(byte value)
        {
            return System.Convert.ToChar((int)value);
        }

        private byte ConvertChar(char value)
        {
           int intValue = System.Convert.ToInt32(value);
           if (intValue >= 0 && intValue <= 255)
           {
               return (byte)intValue;
           }
           else
           {
               byte[] bytes = _BackupEncoding.GetBytes(new char[] { value });
               if (bytes.Length == 1)
               {
                   return bytes[0];
               }
               else
               {
                   //Fallback
                   return ConvertChar('?');
               }
           }
        }
    }
}
